#define TRACE
using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Runtime.InteropServices;
using Dimok;
using ConfigPDF = Dimok.Config.imaging.PDF;
using Dimok.Exceptions;
using Dimok.Data;
using Dimok.Data.Database;
using Dimok.Documents.DataSets;
using Dimok.Images;
using ACodec = Atalasoft.Imaging.Codec;
using AImages = Atalasoft.Imaging;
using A = Acrobat;
using AF = AFORMAUTLib;
using ABC = WebSupergoo.ABCpdf6;
//using PDFKit = TallComponents.PDF;
using Interop.PrepTools;
using Dyno = ceTe.DynamicPDF;
using VB = Microsoft.VisualBasic;

namespace Dimok.Documents {
	/// <summary>
	/// Summary description for PDF.
	/// </summary>
	public class PDF : IDisposable {
		private const int MAX_RIGHT = 2000;
		private const int MAX_TOP = 2000;
		private string FileName;
		private bool IsTemp = false;
		private A.CAcroPDDoc Doc;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Constructor. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="pdfFile">	. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public PDF(byte[] pdfFile) : this( FileManager.GetFileFromBytes(pdfFile) ){
			IsTemp = true;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Constructor. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileName">	. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public PDF(string fileName) {
			FileName = fileName;
			Doc = CreatePDDocInstance(FileName);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Finaliser. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		~PDF(){	Dispose(); }

		#region XXX to PDF

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Tiff to pdf. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileIn">	. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] TiffToPDF(byte[] fileIn){
			if( ConfigPDF.DynamicPDF ){
				Dyno.Document doc = new ceTe.DynamicPDF.Imaging.TiffFile(fileIn).GetDocument();
				doc.InitialPageZoom = Dyno.PageZoom.FitWidth;
				return doc.Draw();
			}
			string fileTiff = Dimok.FileManager.GetFileFromBytes(fileIn,".tif");
			return Dimok.FileManager.GetBytesFromFile(AnyToPDF(fileTiff,"",true),true);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Any to pdf. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileNames">	List of names of the files. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] AnyToPDF(string[] fileNames){
			ArrayList alPdfs = new ArrayList();
			foreach( string fileName in fileNames )
				alPdfs.Add(FileManager.GetBytesFromFile(AnyToPDF(fileName,"",false),true));
			return CombinePDF(alPdfs);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Any to pdf. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="filesIn">	The files in. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] AnyToPDF(byte[][] filesIn){
			ArrayList alPdfs = new ArrayList();
			foreach( byte[] fileIn in filesIn )
				alPdfs.Add(AnyToPDF(fileIn));
			return CombinePDF(alPdfs);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Any to pdf. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileIn">		. </param>
		/// <param name="fileOut">	if empty - automaticaly generate an output file name. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string AnyToPDF(byte[] fileIn,string fileOut){
			return AnyToPDF(FileManager.GetFileFromBytes(fileIn,"."+Enums.GetExtention(fileIn)),fileOut,true);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Any to pdf. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileIn">	. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] AnyToPDF(byte[] fileIn){
			return FileManager.GetBytesFromFile(AnyToPDF(FileManager.GetFileFromBytes(fileIn,"."+Enums.GetExtention(fileIn)),"",true),true);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Any to pdf. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="RemoteException">	Thrown when remote. </exception>
		///
		/// <param name="fileIn">				. </param>
		/// <param name="fileOut">			if empty - automaticaly generate an output file name. </param>
		/// <param name="deleteFileIn">	. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string AnyToPDF(string fileIn,string fileOut,bool deleteFileIn){
			if( fileOut == null || fileOut == "" )fileOut = Path.ChangeExtension(fileIn,"pdf");
			fileOut = FileManager.GetSureFileName(fileOut);
			Acrobat.CAcroAVDoc avDoc = null;
			try {
				try{
					avDoc = CreateAVDocInstance(fileIn);
				}catch{
					avDoc = CreateAVDocInstance(fileIn);
				}
				Acrobat.CAcroPDDoc pdDoc = (Acrobat.CAcroPDDoc)avDoc.GetPDDoc();
				pdDoc.Save((short)(Acrobat.PDSaveFlags.PDSaveFull | Acrobat.PDSaveFlags.PDSaveCollectGarbage | Acrobat.PDSaveFlags.PDSaveLinearized) ,fileOut);
				pdDoc.Close();
				return fileOut;
			}catch(Exception exc){
				throw new RemoteException(fileIn,exc);
			}finally{
				try{avDoc.Close(1);}catch{}
				try{if( deleteFileIn )File.Delete(fileIn);}catch{}
			}
		}
		#endregion

		#region Forms ================

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Fill form tall. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileName">	. </param>
		/// <param name="dataRow">	The data row. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] FillForm_Tall(string fileName,DataRow dataRow){
			return null;
			using( FileStream fs = File.OpenRead(fileName) )
				return FillForm_Tall(fs,dataRow);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Fill form tall. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileIn">		. </param>
		/// <param name="dataRow">	The data row. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] FillForm_Tall(Stream fileIn,DataRow dataRow){
			return null;
			/*
			PDFKit.Document doc = new TallComponents.PDF.Document( new BinaryReader(fileIn) );
			for( int i = 0; i < doc.Fields.Count; i++ ){
				PDFKit.Field field = doc.Fields[i];
				if( dataRow.Table.Columns.Contains(field.Name) ){
					field.Value = dataRow[field.Name]+"";
					field.Flatten = true;
				}
			}
			MemoryStream ms = new MemoryStream();
			BinaryWriter bw = new BinaryWriter(ms);
			doc.Write(bw);
			return ms.ToArray();
			 * */
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Fill form and save it to file. This overload can be used in remoting. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="filesIn">	The files in. </param>
		/// <param name="fields">		. </param>
		///
		/// <returns>	name of output file. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] FillForm(byte[][] filesIn,DataTable fields){return FillForm(filesIn,SQLHelperEx.RowToHashTable(fields));}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Fill form and save it to file. This overload can be used in remoting. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="filesIn">	The files in. </param>
		/// <param name="fields">		. </param>
		///
		/// <returns>	name of output file. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] FillForm(byte[][] filesIn,Hashtable fields){
			return FillForm(CombinePDF(filesIn),fields);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Fill form and save it to file. This overload can be used in remoting. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileIn">	. </param>
		/// <param name="fields">	. </param>
		///
		/// <returns>	name of output file. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] FillForm(byte[] fileIn,DataTable fields){return FillForm(fileIn,SQLHelperEx.RowToHashTable(fields));}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Fill form and save it to file. This overload can be used in remoting. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileIn">	. </param>
		/// <param name="fields">	. </param>
		///
		/// <returns>	name of output file. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] FillForm(byte[] fileIn,Hashtable fields) {
			if( ConfigPDF.UsePrepTools )return FillFormEx(fileIn,fields);
			return FileManager.GetBytesFromFile(FillForm(FileManager.GetFileFromBytes(fileIn,"~~~FillForm.pdf"),string.Empty,fields,true),true);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Fill form and save it to file. This overload can be used in remoting. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileIn">				. </param>
		/// <param name="fileOut">			if empty - automaticaly generate an output file name. </param>
		/// <param name="fields">				. </param>
		/// <param name="deleteFileIn">	. </param>
		///
		/// <returns>	name of output file. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string FillForm(string fileIn,string fileOut,Hashtable fields,bool deleteFileIn){
			return FillForm(fileIn,fileOut,fields,deleteFileIn,ConfigPDF.FlattenFields);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Fill form and save it to file. This overload can be used in remoting. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileIn">				. </param>
		/// <param name="fileOut">			if empty - automaticaly generate an output file name. </param>
		/// <param name="fields">				. </param>
		/// <param name="deleteFileIn">	. </param>
		/// <param name="flatten">			true to flatten. </param>
		///
		/// <returns>	name of output file. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string FillForm(string fileIn,string fileOut,Hashtable fields,bool deleteFileIn,bool flatten){
			if( fileOut == null || fileOut == "" )fileOut = FileManager.BuildFullFileName(fileIn,true);
			Acrobat.CAcroAVDoc avDoc = (Acrobat.CAcroAVDoc)Activator.CreateInstance(Type.GetTypeFromProgID("AcroExch.AVDoc",true),true);
			AF.AFormApp aForm = null;
			AF.Fields aFields = null;
			Acrobat.CAcroPDDoc pdDoc = null;
			try {
				avDoc = CreateAVDocInstance(fileIn);
				aForm = CreateAFormAppInstance();
				aFields = (AF.Fields)aForm.Fields;
				foreach( AF.Field aField in aFields){
					if( fields.ContainsKey(aField.Name) )
						aField.Value = fields[aField.Name].ToString();
					Marshal.ReleaseComObject(aField);
				}
				pdDoc = (Acrobat.CAcroPDDoc)avDoc.GetPDDoc();
				if( flatten )aFields.ExecuteThisJavascript("flattenPages(0,numPages-1)");
				pdDoc.Save((short)(Acrobat.PDSaveFlags.PDSaveFull | Acrobat.PDSaveFlags.PDSaveCollectGarbage | Acrobat.PDSaveFlags.PDSaveLinearized),fileOut);
				pdDoc.Close();
				return fileOut;
			}finally{
				try{avDoc.Close(1);}catch{}
				Dispose(aFields,aForm,pdDoc,avDoc);
				if( deleteFileIn )File.Delete(fileIn);
			}
		}
		// public static byte[] FillFormFDF(string fdfName,string pdfUrl, Hashtable fields){
		// 	FDF.FdfAppClass app = new FDFACXLib.FdfAppClass();
		// 	FDF.FdfDoc doc = (FDF.FdfDoc)app.FDFOpenFromFile(fdfName);
		// 	for( string fieldName = doc.FDFNextFieldName(""); fieldName != "" && fieldName != null;
		// 	fieldName = doc.FDFNextFieldName(fieldName) ){
		// 		if( fields.ContainsKey(fieldName) )
		// 			doc.FDFSetValue(fieldName,fields[fieldName]+"",false);
		// 	}
		// 	doc.FDFSetFile(pdfUrl);
		// 	return (byte[])doc.FDFSaveToBuf();
		// } 
		public static byte[] FillFormEx(byte[] pdf,Hashtable fields){
			string temp = Path.GetTempFileName();
			PDocClass pDoc = new PDocClass();
			if(!pDoc.New(temp,592,842)) throw new Exception("Could not create new PrepTool output file "+temp);
			IDocClass iDoc = new IDocClass();
			if(!iDoc.OpenMem(pdf,"")) throw new Exception("Couldnt load pdf template "+pdf+" for PrepTool input");
			pDoc.Attach(iDoc);
			FormField field = null;
			for( int i = 1; (field = iDoc.GetFormField(i,1)) != null; i++ ){
				if( fields.ContainsKey(field.Name) )pDoc.InputSetFormData(field.Name,fields[field.Name]+"",PTFormFlags.PTFlagFormLeaveAsIs,PTAnnotFlags.PTFlagAnnotLeaveAsIs);
			}
			pDoc.InputCopyPages(0,iDoc.NumPages());
			//iDoc.Close();
			pDoc.Close();
			return FileManager.GetBytesFromFile(temp,true);
		}
		#endregion

		#region PrepButtonTemplate

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Prep button template. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="buttonTemplate">	The button template. </param>
		/// <param name="buttonField">		The button field. </param>
		/// <param name="actionWebPage">	The action web page. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] PrepButtonTemplate(byte[] buttonTemplate,string buttonField,string actionWebPage) {
			return PrepButtonTemplate(buttonTemplate,buttonField,actionWebPage,256);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Prep button template. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="buttonTemplate">	The button template. </param>
		/// <param name="buttonField">		The button field. </param>
		/// <param name="actionWebPage">	The action web page. </param>
		/// <param name="flags">					The flags. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] PrepButtonTemplate(byte[] buttonTemplate,string buttonField,string actionWebPage,int flags) {
			string template = FileManager.GetFileFromBytes(buttonTemplate,".pdf",true);
			string temp = null;
			A.CAcroAVDoc avDoc = null;
			AF.AFormApp aForm = null;
			AF.Fields aFields = null;
			Acrobat.CAcroPDDoc pdDoc = null;
			AF.Field button = null;
			try {
				avDoc = CreateAVDocInstance(template);
				pdDoc = (A.CAcroPDDoc)avDoc.GetPDDoc();
				pdDoc.GetInfo("");
				aForm = CreateAFormAppInstance();
				aFields = (AF.Fields)aForm.Fields;
				button = (AF.Field)aFields[buttonField];
				button.SetSubmitFormAction("up",actionWebPage,flags,Missing.Value);
				temp = FileManager.BuildFullFileName("Button.pdf",true);
				pdDoc.Save((short)(A.PDSaveFlags.PDSaveFull | A.PDSaveFlags.PDSaveCollectGarbage | A.PDSaveFlags.PDSaveLinearized),Path.Combine(Directory.GetCurrentDirectory(),temp));
				pdDoc.Close();
				File.Delete(template);
			}catch(Exception exc){
				throw new Exception("TempPdf:"+template+"\nButtonName:"+buttonField,exc);
			}finally {
				try{avDoc.Close(1);}catch{}
				Dispose(button,aFields,aForm,pdDoc,avDoc);
			}
			return FileManager.GetBytesFromFile(temp,true);
		}
		#endregion

		#region Page operations
		
		#region CombinePDF

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Combine pdf. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="files">	The files. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] CombinePDF(ArrayList files) {
			return CombinePDF((byte[][])files.ToArray(typeof(byte[])));
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Combine pdf. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="files">	The files. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] CombinePDF(byte[][] files) {
			if( ConfigPDF.DynamicPDF )return CombinePDF_Dyno(files);
			if(ConfigPDF.UsePrepTools) return CombinePDFs_Prep(files);
			if(ConfigPDF.AbcPDF) return CombinePDF_ABC(files);
			return CombinePdfs(files);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Combine pdf. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="fileNames">	List of names of the files. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] CombinePDF(string[] fileNames) {
			if( ConfigPDF.DynamicPDF )return CombinePDF_Dyno(fileNames);
			throw new Exception("Dynamic PDF is turned off."+Environment.NewLine+"No other module is specified as a handler for this operation.");
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Combine pd file system prep. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="pdfs">	The pdfs. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] CombinePDFs_Prep(byte[][] pdfs) {
			if( pdfs.Length == 1 )return pdfs[0];
			string temp = FileManager.BuildFullFileName(".pdf",true);
			PDocClass pDoc = new PDocClass();
			if(!pDoc.New(temp,592,842)) throw new Exception("Could not create new PrepTool output file "+temp);
			foreach(byte[] pdf in pdfs) {
				IDocClass iDoc = new IDocClass();
				if(!iDoc.OpenMem(pdf,"")) throw new Exception("Couldnt load pdf template "+pdf+" for PrepTool input");
				pDoc.Attach(iDoc);
				pDoc.InputCopyPages(0,iDoc.NumPages());
				iDoc.Close();
			}
			pDoc.Close();
			return FileManager.GetBytesFromFile(temp,true);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Combine pdf dyno. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="files">	The files. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] CombinePDF_Dyno(byte[][] files){
			if(files.Length == 1) return files[0];
			Dyno.Merger.MergeDocument doc = new ceTe.DynamicPDF.Merger.MergeDocument();
			foreach( byte[] file in files )
				doc.Append(new Dyno.Merger.PdfDocument(new MemoryStream(file)),new Dyno.Merger.MergeOptions(true));
			doc.InitialPageZoom = Dyno.PageZoom.FitWidth;
			return doc.Draw();
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Combine pdf dyno. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="files">	The files. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] CombinePDF_Dyno(string[] files){
			Dyno.Merger.MergeDocument doc = new ceTe.DynamicPDF.Merger.MergeDocument();
			foreach( string file in files )
				doc.Append(file,new Dyno.Merger.MergeOptions(true));
			doc.InitialPageZoom = Dyno.PageZoom.FitWidth;
			return doc.Draw();
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Combine pdf abc. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="files">	The files. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] CombinePDF_ABC(byte[][] files) {
			ABC.Doc docAll = new WebSupergoo.ABCpdf6.Doc();
			foreach(byte[] file in files) {
				ABC.Doc doc = new WebSupergoo.ABCpdf6.Doc();
				doc.Read(file);
				docAll.Append(doc);
				doc.Clear();
			}
			try {
				return docAll.GetData();
			} finally {
				docAll.Clear();
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Combine pdfs. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="files">	The files. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] CombinePdfs(byte[][] files) {
			return FileManager.GetBytesFromFile(CombinePdfs(files,""),true);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Combine pdfs. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="files">		The files. </param>
		/// <param name="fileOut">	if empty - automaticaly generate an output file name. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string CombinePdfs(byte[][] files,string fileOut) {
			StringList slNames = new StringList();
			try{
				foreach( byte[] file in files )
					slNames.Add(FileManager.GetFileFromBytes(file,"."+Enums.GetExtention(file),true));
				return CombinePdfs(slNames,fileOut);
			}finally{
				FileManager.DeleteFiles((string[])slNames);
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Combine pdfs. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileNames">	List of names of the files. </param>
		/// <param name="fileOut">		if empty - automaticaly generate an output file name. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string CombinePdfs(string[] fileNames,string fileOut) {
			return CombinePdfs(fileNames,fileOut,false);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Combine pdfs. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="FileLoadException">	Thrown when fileload. </exception>
		///
		/// <param name="fileNames">		List of names of the files. </param>
		/// <param name="fileOut">			if empty - automaticaly generate an output file name. </param>
		/// <param name="deleteFiles">	true to delete the files. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string CombinePdfs(string[] fileNames,string fileOut,bool deleteFiles) {
			Acrobat.CAcroPDDoc pdNewDoc = (Acrobat.CAcroPDDoc)Activator.CreateInstance(Type.GetTypeFromProgID("AcroExch.PDDoc",true),true);
			fileOut = FileManager.BuildFullFileName(fileOut,"pdf",true);
			Acrobat.CAcroPDDoc pdDoc = (Acrobat.CAcroPDDoc)Activator.CreateInstance(Type.GetTypeFromProgID("AcroExch.PDDoc",true),true);
			try{
				int res = Convert.ToInt32(pdNewDoc.Open(fileNames[0]));
				if( res != -1 ) throw new System.IO.FileLoadException("Acrobat can't load file "+fileNames[0]);
				for(int i = 1; i<fileNames.Length; i++) {
					if(new FileInfo(fileNames[i]).Length == 0) continue;
					res = Convert.ToInt32(pdDoc.Open(fileNames[i]));
					if( res != -1 ) throw new System.IO.FileLoadException("Acrobat can't load file "+fileNames[i]);
					res = Convert.ToInt32(pdNewDoc.InsertPages(pdNewDoc.GetNumPages()-1,pdDoc,0,pdDoc.GetNumPages(),0));
					if( res != -1 ) throw new System.IO.FileLoadException("Acrobat can't insert file "+fileNames[i]);
					pdDoc.Close();
				}
				pdNewDoc.Save((short)(Acrobat.PDSaveFlags.PDSaveFull | Acrobat.PDSaveFlags.PDSaveCollectGarbage | Acrobat.PDSaveFlags.PDSaveLinearized),fileOut);
			}finally{
				try{Marshal.ReleaseComObject(pdDoc);}catch{}
				try{pdNewDoc.Close();}catch{}
				try{Marshal.ReleaseComObject(pdNewDoc);}catch{}
			}
			return fileOut;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Uses Acrobat. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileName">	. </param>
		/// <param name="dirOut">		. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string Slice(string fileName,string dirOut){
			return Slice_Acrobat(fileName,dirOut);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Slice acrobat. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="FileLoadException">	Thrown when fileload. </exception>
		///
		/// <param name="fileName">	. </param>
		/// <param name="dirOut">		. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string Slice_Acrobat(string fileName,string dirOut) {
			if( !Directory.Exists(dirOut) )Directory.CreateDirectory(dirOut);
			else FileManager.DeleteFiles(dirOut);
			string fileOut = FileManager.GetFileFromBytes(new byte[]{},Path.Combine(dirOut,"Page.pdf"),true);
			Acrobat.CAcroPDDoc pdDoc = (Acrobat.CAcroPDDoc)Activator.CreateInstance(Type.GetTypeFromProgID("AcroExch.PDDoc",true),true);
			Acrobat.CAcroPDDoc pdDocPage = (Acrobat.CAcroPDDoc)Activator.CreateInstance(Type.GetTypeFromProgID("AcroExch.PDDoc",true),true);
			try{
				int res = Convert.ToInt32(pdDoc.Open(fileName));
				if( res != -1 ) throw new System.IO.FileLoadException("Acrobat can't load file "+fileName);
				for(int i = 0; i < pdDoc.GetNumPages(); i++) {
					res = Convert.ToInt32(pdDocPage.Create());
					if( res != -1 ) throw new System.IO.FileLoadException("Acrobat can't create new file.");
					res = Convert.ToInt32(pdDocPage.InsertPages(-1, pdDoc, i, 1, 0));
					if( res != -1 ) throw new System.IO.FileLoadException("Acrobat can't insert "+i+" page.");
					pdDocPage.Save((short)(Acrobat.PDSaveFlags.PDSaveFull | Acrobat.PDSaveFlags.PDSaveCollectGarbage | Acrobat.PDSaveFlags.PDSaveLinearized),FileManager.BuildFullFileName(fileOut,true));
					pdDocPage.Close();
				}
			}catch{
				try{FileManager.DeleteFiles(dirOut);}catch{}
				throw;
			}finally{
				try{Marshal.ReleaseComObject(pdDocPage);}catch{}
				try{pdDoc.Close();}catch{}
				try{Marshal.ReleaseComObject(pdDoc);}catch{}
				try{File.Delete(fileOut);}catch{}
			}
			return dirOut;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the pages acrobat. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="file">		The file. </param>
		/// <param name="pages">	The pages. </param>
		///
		/// <returns>	The pages acrobat. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string GetPages_Acrobat(byte[] file,string pages){
			 return GetPages_Acrobat(file,(int[])new StringList(pages));
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the pages acrobat. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="file">		The file. </param>
		/// <param name="pages">	The pages. </param>
		///
		/// <returns>	The pages acrobat. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string GetPages_Acrobat(byte[] file,params int[] pages){
			string fileName = FileManager.GetFileFromBytes(file,".pdf");
			try{return GetPages_Acrobat(fileName,pages);
			}finally{File.Delete(fileName);}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the pages acrobat. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="FileLoadException">	Thrown when fileload. </exception>
		///
		/// <param name="fileName">	. </param>
		/// <param name="pages">		The pages. </param>
		///
		/// <returns>	The pages acrobat. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string GetPages_Acrobat(string fileName,params int[] pages) {
			string fileOut = FileManager.GetSureFileName(fileName);
			if( FileManager.IsAllPages(pages) )
				File.Copy(fileName,fileOut);
			else{
				Acrobat.CAcroPDDoc pdDoc = (Acrobat.CAcroPDDoc)Activator.CreateInstance(Type.GetTypeFromProgID("AcroExch.PDDoc",true),true);
				Acrobat.CAcroPDDoc pdDocPage = (Acrobat.CAcroPDDoc)Activator.CreateInstance(Type.GetTypeFromProgID("AcroExch.PDDoc",true),true);
				try{
					int res = Convert.ToInt32(pdDoc.Open(fileName));
					if( res != -1 ) throw new System.IO.FileLoadException("Acrobat can't load file "+fileName);
					ArrayListEx alPages = FileManager.MakePageNumbers(pdDoc.GetNumPages(),pages);
					res = Convert.ToInt32(pdDocPage.Create());
					if( res != -1 ) throw new System.IO.FileLoadException("Acrobat can't create new file.");
					for(int i = 0; i < alPages.Count; i++) {
						res = Convert.ToInt32(pdDocPage.InsertPages(-1,pdDoc,(int)alPages[i]-1,1,0));
						if( res != -1 ) throw new System.IO.FileLoadException("Acrobat can't insert "+i+" page.");
					}
					pdDocPage.Save((short)(Acrobat.PDSaveFlags.PDSaveFull | Acrobat.PDSaveFlags.PDSaveCollectGarbage | Acrobat.PDSaveFlags.PDSaveLinearized),fileOut);
					pdDocPage.Close();
				}finally{
					try{Marshal.ReleaseComObject(pdDocPage);}catch{}
					try{pdDoc.Close();}catch{}
					try{Marshal.ReleaseComObject(pdDoc);}catch{}
				}
			}
			return fileOut;
		}
		#endregion

		#region PageCount

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Page count. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="MergerException">	Thrown when merger. </exception>
		/// <exception cref="IOException">			Thrown when an IO failure occurred. </exception>
		///
		/// <param name="fileName">	. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static int PageCount(string fileName){
			if (ConfigPDF.AbcPDF) return ABCPdf.PageCount(fileName);
			try{
				Dyno.Merger.MergeDocument doc = new Dyno.Merger.MergeDocument(new Dyno.Merger.PdfDocument(FileManager.GetBytesFromFile(fileName)));
				return doc.Pages.Count;
			}catch(Dyno.Merger.MergerException exc){
				if( Dimok.Common.GetMethod(1) == Dimok.Common.GetMethod(0) )throw exc;
				Decrypt(fileName);
				return PageCount(fileName);
			}catch(IOException exc){
				if( exc.Message == "An attempt was made to move the file pointer before the beginning of the file.\r\n" )
					return 0;
				throw exc;
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Page count acrobat. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileName">	. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static int PageCount_Acrobat(string fileName){
			Common.TraceMe("Start");
			int pc = CreatePDDocInstance(fileName).GetNumPages();
			Common.TraceMe("End");
			return pc;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Page count prep. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileName">	. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static int PageCount_Prep(string fileName){
			IDocClass iDoc = new IDocClass();
			iDoc.Open(fileName,"");
			try{
				return Math.Max(0,iDoc.NumPages());
			}finally{
				iDoc.Close();
			}
		}
		#endregion

		#region GetPages

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get range of pages from pdf file. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileName">	. </param>
		///
		/// ### <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[]GetPages(string fileName){return GetPages(fileName,-1);}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get range of pages from pdf file. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="pdfFile">	. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[]GetPages(byte[] pdfFile){return GetPages(pdfFile,-1);}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get range of pages from pdf file. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="fileName">			. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	The pages. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] GetPages(string fileName,params int[] pageNumbers){
			if( FileManager.IsAllPages(pageNumbers) )return FileManager.GetBytesFromFile(fileName);
			if (ConfigPDF.DynamicPDF) return GetPages_Dyno(new Dyno.Merger.PdfDocument(fileName), pageNumbers);
			if (ConfigPDF.AbcPDF) return GetPages(FileManager.GetBytesFromFile(fileName), pageNumbers);
			throw new Exception("Unspecified PDF Tool!");
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get range of pages from pdf file. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="file">					The file. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	The pages. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] GetPages(byte[] file,params int[] pageNumbers){
			if( FileManager.IsAllPages(pageNumbers) )return file;
			if (ConfigPDF.DynamicPDF) return GetPages_Dyno(new Dyno.Merger.PdfDocument(file), pageNumbers);
			if (ConfigPDF.AbcPDF) return ABCPdf.GetPages(file, pageNumbers);
			throw new Exception("Unspecified PDF Tool!");
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Static constructor. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="doc">					The document. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static byte[]GetPages_Dyno(Dyno.Merger.PdfDocument doc,int[] pageNumbers){
			Dyno.Merger.MergeDocument docOut = new ceTe.DynamicPDF.Merger.MergeDocument();
			foreach( int pageNumber in FileManager.MakePageNumbers(doc.Pages.Count,pageNumbers) )
				docOut.Append(doc,pageNumber,1,new Dyno.Merger.MergeOptions(true));
			docOut.InitialPageZoom = Dyno.PageZoom.FitWidth;
			return docOut.Draw();
		}
		#endregion GetPages

		#region GetPages(Old)

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Get range of pages from pdf file. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="pdfFile">		. </param>
		/// <param name="startPage">	1 based (-1 - 1st page) </param>
		/// <param name="count">			-1 - all pages. </param>
		///
		/// ### <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static byte[]GetPages(byte[] pdfFile,int startPage,int count){
			PDocClass pDoc = new PDocClass();
			bool deleteInFile = false;
			string temp = Path.GetTempFileName();
			string fileName = pdfFile.Length < 1024 ? Encoding.ASCII.GetString(pdfFile) : "";
			if( !File.Exists(fileName ) ){
				deleteInFile = true;
				fileName = FileManager.GetFileFromBytes(pdfFile,Path.GetTempFileName(),false);
			}
			if(!pDoc.New(temp,592,842)) throw new Exception("Couldn't create a new PDF file for output");
			if(!pDoc.InputOpen(fileName)) throw new Exception("Couldn't load pdf file from "+fileName);
			if( startPage <= 0 )startPage = 1;
			int endPage =  count <= 0 ? - 1 : startPage + count - 1;
			pDoc.InputCopyPages(startPage,endPage);
			pDoc.Close();
			if( deleteInFile )File.Delete(fileName);
			return FileManager.GetBytesFromFile(temp,true);
		}
		#endregion
		
		#region AddPages

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Add pages to fileTo. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="imageFrom">		The image from. </param>
		/// <param name="fileTo">				. </param>
		/// <param name="pageAfter">		. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(byte[] imageFrom, string fileTo,int pageAfter,params int[] pageNumbers){
			byte[] fileOut = ABCPdf.AddPages(imageFrom,File.Exists(fileTo)?FileManager.GetBytesFromFile(fileTo):null,pageAfter,pageNumbers);
			FileManager.GetFileFromBytes(fileOut,fileTo,false);
		}
		#endregion

		#region AddPages(Old)

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Add pages to fileTo. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileTo">			. </param>
		/// <param name="image">			The image. </param>
		/// <param name="pageAfter">	. </param>
		/// <param name="pageStart">	. </param>
		/// <param name="count">			. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string AddPages(string fileTo,byte[] image,int pageAfter,int pageStart,int count){
			string fileFrom = FileManager.GetFileFromBytes(image);
			try{ return AddPages(fileTo,fileFrom,pageAfter,pageStart,count); }
			finally{ File.Delete(fileFrom);}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Add pages to fileTo. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="fileTo">			. </param>
		/// <param name="fileFrom">		. </param>
		/// <param name="pageAfter">	. </param>
		/// <param name="pageStart">	. </param>
		/// <param name="count">			. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string AddPages(string fileTo,string fileFrom,int pageAfter,int pageStart,int count){
			int pageEnd =  CalcEndPage(ref pageStart,count);
			pageAfter  = Math.Max(pageAfter,0);

			string temp = Path.GetTempFileName();
			PDocClass pDoc = new PDocClass();
			if(!pDoc.New(temp,592,842)) throw new Exception("Couldn't create a new PDF file for output");

			if( pageAfter > 0 ){
				if(!pDoc.InputOpen(fileTo)) throw new Exception("Couldn't load pdf file from "+fileTo);
				pDoc.InputCopyPages(1,pageAfter);
			}

			if(!pDoc.InputOpen(fileFrom)) throw new Exception("Couldn't load pdf file from "+fileFrom);
			pDoc.InputCopyPages(pageStart,pageEnd);

			if(!pDoc.InputOpen(fileTo)) throw new Exception("Couldn't load pdf file from "+fileTo);
			pDoc.InputCopyPages(pageAfter+1,-1);

			pDoc.Close();
			File.Delete(fileTo);
			File.Move(temp,fileTo);
			return fileTo;
		}
		#endregion

		#region DeletePages

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileName">			. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string DeletePages(string fileName,params int[] pageNumbers){
			if( FileManager.IsAllPages(pageNumbers) )
				File.Delete(fileName);
			else{
				byte[] fileOut = ABCPdf.DeletePages(FileManager.GetBytesFromFile(fileName), pageNumbers);
				if (fileOut.Length == 0) File.Delete(fileName);
				else FileManager.GetFileFromBytes(fileOut, fileName, false);
			}
			return fileName;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="doc">					The document. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static Dyno.Merger.MergeDocument DeletePages(Dyno.Merger.MergeDocument doc,params int[] pageNumbers){
			ArrayList alPages = new ArrayList();
			foreach( int pageNumber in FileManager.MakePageNumbers(doc.Pages.Count,pageNumbers) )
				alPages.Add(doc.Pages[pageNumber-1]);
			foreach( Dyno.Page page in alPages )
				doc.Pages.Remove(page);
			return doc;
		}
		#endregion

		#region DeletePages(Old)

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="fileName">		. </param>
		/// <param name="pageStart">	. </param>
		/// <param name="count">			. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string DeletePages(string fileName,int pageStart,int count){
			int pageEnd =  CalcEndPage(ref pageStart,count);

			string temp = Path.GetTempFileName();
			PDocClass pDoc = new PDocClass();
			if(!pDoc.New(temp,592,842)) throw new Exception("Couldn't create a new PDF file for output");

			if(!pDoc.InputOpen(fileName)) throw new Exception("Couldn't load pdf file from "+fileName);
			if( pageStart-1 > 0 )pDoc.InputCopyPages(1,pageStart-1);
			pDoc.InputCopyPages(pageEnd+1,-1);

			pDoc.Close();
			File.Delete(fileName);
			File.Move(temp,fileName);
			return fileName;
		}
		#endregion

		#region MovePages

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Move pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileFrom">			. </param>
		/// <param name="fileTo">				. </param>
		/// <param name="pageAfter">		. </param>
		/// <param name="copy">					true to copy. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void MovePages(string fileFrom, string fileTo, int pageAfter, bool copy, params int[] pageNumbers) {
			byte[] fileOut;
			if (fileFrom.ToLower() == fileTo.ToLower())
				fileOut = ABCPdf.MovePages(FileManager.GetBytesFromFile(fileFrom), pageAfter, copy, pageNumbers);
			else
				fileOut = ABCPdf.MovePages(FileManager.GetBytesFromFile(fileFrom),
					File.Exists(fileTo) ? FileManager.GetBytesFromFile(fileTo) : null, pageAfter, copy, pageNumbers);
			FileManager.GetFileFromBytes(fileOut, fileTo, false);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Move pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="docFrom">			The document from. </param>
		/// <param name="docTo">				The document to. </param>
		/// <param name="pageAfter">		. </param>
		/// <param name="copy">					true to copy. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static void MovePages(Dyno.Merger.MergeDocument docFrom,Dyno.Merger.MergeDocument docTo,int pageAfter,bool copy, params int[] pageNumbers){
			foreach( int pageNumber in FileManager.MakePageNumbers(docFrom.Pages.Count,pageNumbers) )
				docTo.Pages.Insert(pageAfter++,docFrom.Pages[pageNumber-1]);
			if( !copy )DeletePages(docFrom,pageNumbers);
		}
		#endregion MovePages

		#region MovePages(Old)

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Move pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="fileName">		. </param>
		/// <param name="pageAfter">	. </param>
		/// <param name="pageStart">	. </param>
		/// <param name="count">			. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string MovePages(string fileName,int pageAfter,int pageStart, int count){
			pageStart  = Math.Max(pageStart,1);
			int pageEnd =  CalcEndPage(ref pageStart,count);
			pageAfter  = Math.Max(pageAfter,0);

			string temp = Path.GetTempFileName();
			PDocClass pDoc = new PDocClass();
			if(!pDoc.New(temp,592,842)) throw new Exception("Couldn't create a new PDF file for output");

			if(!pDoc.InputOpen(fileName)) throw new Exception("Couldn't load pdf file from "+fileName);

			if( pageStart < pageAfter ){
				if( pageStart > 1 )pDoc.InputCopyPages(1,pageStart-1);
				pDoc.InputCopyPages(pageStart+count,pageAfter);
				pDoc.InputCopyPages(pageStart,pageEnd);
				pDoc.InputCopyPages(pageAfter+1,-1);
			}else{
				if( pageAfter > 0 )pDoc.InputCopyPages(1,pageAfter);
				pDoc.InputCopyPages(pageStart,pageEnd);
				pDoc.InputCopyPages(pageAfter+1,pageStart-1);
				pDoc.InputCopyPages(pageStart+1,-1);
			}

			pDoc.Close();
			File.Delete(fileName);
			File.Move(temp,fileName);
			return fileName;
			//throw new Exception("Moving PDF pages is not implemented.");
		}
		#endregion

		#endregion Page operations

		#region Dyno Helpers

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a un attached merge document. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileName">	. </param>
		///
		/// <returns>	The un attached merge document. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static Dyno.Merger.MergeDocument GetUnAttachedMergeDocument(string fileName){
			if( PageCount(fileName) > 0 )
				return new Dyno.Merger.MergeDocument(new Dyno.Merger.PdfDocument(FileManager.GetBytesFromFile(fileName)));
			return new Dyno.Merger.MergeDocument();
		}
		#endregion

		#region DocToPDR

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Document to pdr. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="pdfFile">	. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string DocToPDR(string pdfFile){
			try{
				Acrobat.CAcroPDDoc pdDoc = CreatePDDocInstance(pdfFile);
				string newFile = pdfFile+".pdf";
				try{
					pdDoc.Open(pdfFile);
					pdDoc.Save(1,newFile);
				}finally{
					pdDoc.Close();
					Marshal.ReleaseComObject(pdDoc);
				}
				return newFile;
			}catch(Exception exc){
				throw new Exception("PDF File Name:"+pdfFile,exc);
			}
		}
		#endregion DocToPDR

		#region LinearizePdf

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Linearize pdf. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="pdfFile">	. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] LinearizePdf(byte[] pdfFile){
			return FileManager.GetBytesFromFile(LinearizePdf(FileManager.GetFileFromBytes(pdfFile,".pdf"),"",true),true);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Linearize pdf. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="pdfFileName">		Filename of the pdf file. </param>
		/// <param name="pdfNewFileName">	Filename of the pdf new file. </param>
		/// <param name="deleteInputPdf">	true to delete the input pdf. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string LinearizePdf(string pdfFileName,string pdfNewFileName,bool deleteInputPdf){
			if( pdfNewFileName == "" )pdfNewFileName = FileManager.BuildFullFileName(".pdf",true);
			PDFLinearizerClass pLin = new PDFLinearizerClass();
			pLin.OpenInput(pdfFileName,"");
			pLin.SaveFile(pdfNewFileName);
			if(deleteInputPdf)File.Delete(pdfFileName);
			return pdfNewFileName;
		}
		#endregion

		#region GetText

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the text. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <returns>	The text. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public string[] GetText(){ return GetText(0,0,MAX_TOP,MAX_RIGHT); }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the text. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="bottom">	The bottom. </param>
		/// <param name="left">		The left. </param>
		/// <param name="top">		The top. </param>
		/// <param name="right">	The right. </param>
		///
		/// <returns>	The text. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public string[] GetText(int bottom,int left,int top,int right){
			return GetText(Doc,bottom,left,top,right);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the text. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="pdfFile">	. </param>
		///
		/// <returns>	The text. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string[] GetText(byte[] pdfFile){return GetText(pdfFile,0,0,MAX_TOP,MAX_RIGHT);}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the text. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="pdfFile">	. </param>
		/// <param name="bottom">		The bottom. </param>
		/// <param name="left">			The left. </param>
		/// <param name="top">			The top. </param>
		/// <param name="right">		The right. </param>
		/// <param name="pages">		The pages. </param>
		///
		/// <returns>	The text. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string[] GetText(byte[] pdfFile,int bottom,int left,int top,int right,params int[] pages){
			string fileName = FileManager.GetFileFromBytes(pdfFile);
			try{return GetText(fileName,bottom,left,top,right,pages);
			}finally{File.Delete(fileName);}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the text. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="pdfFile">	. </param>
		///
		/// <returns>	The text. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string[] GetText(string pdfFile){ return GetText(pdfFile,0,0,MAX_TOP,MAX_RIGHT); }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the text. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="pdfFile">	. </param>
		/// <param name="bottom">		The bottom. </param>
		/// <param name="left">			The left. </param>
		/// <param name="top">			The top. </param>
		/// <param name="right">		The right. </param>
		///
		/// <returns>	The text. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string[] GetText(string pdfFile,int bottom,int left,int top,int right){
			return GetText(pdfFile,bottom,left,top,right,-1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the text. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="pdfFile">			. </param>
		/// <param name="bottom">				The bottom. </param>
		/// <param name="left">					The left. </param>
		/// <param name="top">					The top. </param>
		/// <param name="right">				The right. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	The text. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string[] GetText(string pdfFile,int bottom,int left,int top,int right,params int[] pageNumbers){
			try{
				A.CAcroPDDoc pdDoc = CreatePDDocInstance(pdfFile);
				try{
					return 	GetText(pdDoc,bottom,left,top,right,pageNumbers);
				}finally{
					pdDoc.Close();
					Marshal.ReleaseComObject(pdDoc);
				}
			}catch(Exception exc){
				throw new Exception("PDF File Name:"+pdfFile,exc);
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the text. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="pdDoc">				The pd document. </param>
		/// <param name="bottom">				The bottom. </param>
		/// <param name="left">					The left. </param>
		/// <param name="top">					The top. </param>
		/// <param name="right">				The right. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	The text. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static string[] GetText(A.CAcroPDDoc pdDoc,int bottom,int left,int top,int right,params int[] pageNumbers){
			if( bottom < 0 )bottom = top + bottom;
			if( top < 0 )top = bottom - top;
			pageNumbers = FileManager.MakePageNumbers(pdDoc.GetNumPages(),pageNumbers);
			StringBuilder text = new StringBuilder();
			StringList alPages = new StringList();
			A.CAcroRect rect = (Acrobat.CAcroRect)Activator.CreateInstance(Type.GetTypeFromProgID("AcroExch.Rect",true),true);
			foreach( int p in pageNumbers ){
				//object js = pdDoc.GetJSObject();
				//object oRet = VB.Interaction.CallByName(js,"getPageNthWord",VB.CallType.Method,p-1,0);
				rect.Top = (short)top;//point.y;
				rect.Left = (short)left;
				rect.right = (short)right;//point.x;
				rect.bottom = (short)bottom;
				A.CAcroPDTextSelect textSelect = (A.CAcroPDTextSelect)pdDoc.CreateTextSelect(p-1,rect);
				for( int i = 0; i < textSelect.GetNumText(); i++ )
					text.Append(textSelect.GetText(i));
				alPages.Add(text.ToString());
				text.Remove(0,text.Length);
				Marshal.ReleaseComObject(textSelect);
				//textSelect.Destroy();
			}
			Marshal.ReleaseComObject(rect);
			return alPages;
		}
		#endregion

		#region ReadForm

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Reads a form. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="file">			The file. </param>
		/// <param name="dsMatrix">	The ds matrix. </param>
		///
		/// <returns>	The form. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static PdfToDbDs.FieldsDataTable ReadForm(byte[] file, DataSet dsMatrix) {
			string fileName = FileManager.GetFileFromBytes(file, ".pdf");
			try {
				return ReadForm(fileName, (MatrixDS)dsMatrix);
			} finally {
				File.Delete(fileName);
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Reads a form. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileName">	. </param>
		/// <param name="dsMatrix">	The ds matrix. </param>
		///
		/// <returns>	The form. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static PdfToDbDs.FieldsDataTable ReadForm(string fileName, DataSet dsMatrix) {
			return ReadForm(fileName, (MatrixDS)dsMatrix);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Reads a form. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileName">	. </param>
		/// <param name="dsMatrix">	The ds matrix. </param>
		///
		/// <returns>	The form. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static PdfToDbDs.FieldsDataTable ReadForm(string fileName, MatrixDS dsMatrix) {
			PdfToDbDs.FieldsDataTable dtFields = new PdfToDbDs().Fields;
			for( int r = 0; r < dsMatrix.tpdf_FindText.Count; r++ ){
				MatrixDS.tpdf_FindTextRow row = dsMatrix.tpdf_FindText[r];
				Matrix.TextBox[] tbList = PDF.FindText(fileName,row.Text,row.LineText,row.Height,row.Width,row.VStep,row.HStep,row.TopMax,row.TopMin,row.Left,new StringList(row.Pages));
				for( int tb=0; tb < tbList.Length; tb++ )
					foreach( ValuePart vp in ExtractValue(tbList[tb].Text,row.ExtractPattern,tbList[tb].PageNumber,row.FieldName) )
						dtFields.AddFieldsRow(row.FormName,row.TableName,vp.FieldName,row.IndexNumber,vp.PageNumber,vp.FieldValue,row.PagesAppl,row.PagesCoAppl);
				if( r <= 2 && dtFields.Count <= r-1 ){
					dtFields.Clear();
					break;
				}
			}
			return dtFields;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Extracts the value. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="text">				The text. </param>
		/// <param name="pattern">		The pattern. </param>
		/// <param name="pageNumber">	The page number. </param>
		/// <param name="fieldName">	Name of the field. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected static ValuePartList ExtractValue(string text, string pattern,int pageNumber,string fieldName){
			Match m = Regex.Match(text,pattern,RegexOptions.IgnoreCase);
			Regex rePage = new Regex("<p(\\d+)+>",RegexOptions.Compiled);
			Match mPage = rePage.Match(fieldName);
			if( mPage.Success ){
				fieldName = rePage.Replace(fieldName,"");
				pageNumber = int.Parse(mPage.Groups[1].Value);
			}
			MatchCollection pages = Regex.Matches(pattern,"<p(\\d+)+>");
			ValuePartList vpl = new ValuePartList();
			foreach( Match page in pages ){
				Group group = page.Groups[1];
				vpl.Add(new ValuePart(group.Value,fieldName,m.Groups["p"+group.Value].Value));
			}
			if( vpl.Count == 0 )
				if( m.Groups.Count == 1 )
					vpl.Add(new ValuePart(pageNumber,fieldName,m.Groups[m.Groups.Count-1].Value));
				else{
					string sValue = "";
					for( int g = 1; g < m.Groups.Count; g++ )
						sValue += m.Groups[g].Value;
					vpl.Add(new ValuePart(pageNumber,fieldName,sValue));
				}
			return vpl;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	List of value parts. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected class ValuePartList : ArrayList{
			public ValuePartList():base(){}
			public new ValuePart this[int index]{get{return (ValuePart)base[index];}}
			public int Add(ValuePart valuePart) {
				return valuePart.FieldValue == "" ? -1 : base.Add(valuePart);
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Value part. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected struct ValuePart{
			public int PageNumber;
			public string FieldName;
			public string FieldValue;
			public ValuePart(string pageNumber,string fieldName,string fieldValue):
									this(int.Parse(pageNumber),fieldName,fieldValue){}
			public ValuePart(int pageNumber,string fieldName,string fieldValue){
				PageNumber = pageNumber;
				FieldName = fieldName;
				FieldValue = fieldValue;
			}
		}
		#endregion ReadForm

		#region FindText

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Searches for the first text. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="file">					The file. </param>
		/// <param name="pattern">			The pattern. </param>
		/// <param name="linePattern">	The line pattern. </param>
		/// <param name="height">				The height. </param>
		/// <param name="width">				The width. </param>
		/// <param name="vStep">				The v step. </param>
		/// <param name="hStep">				Amount to increment by. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	The found text. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static Matrix.TextBoxList FindText(byte[] file,string pattern,string linePattern,int height,int width,int vStep,int hStep,params int[] pageNumbers){
			return FindText(file,pattern,linePattern,height,width,vStep,hStep,int.MaxValue,int.MinValue,0,pageNumbers);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Searches for the first text. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="file">					The file. </param>
		/// <param name="pattern">			The pattern. </param>
		/// <param name="linePattern">	The line pattern. </param>
		/// <param name="height">				The height. </param>
		/// <param name="width">				The width. </param>
		/// <param name="vStep">				The v step. </param>
		/// <param name="hStep">				Amount to increment by. </param>
		/// <param name="topMax">				The top maximum. </param>
		/// <param name="topMin">				The top minimum. </param>
		/// <param name="left">					The left. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	The found text. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static Matrix.TextBoxList FindText(byte[] file,string pattern,string linePattern,int height,int width,int vStep,int hStep,int topMax,int topMin,int left,params int[] pageNumbers){
			string fileName = FileManager.GetFileFromBytes(file,".pdf");
			try{ return FindText(fileName,pattern,linePattern,height,width,vStep,hStep,topMax,topMin,left,pageNumbers);
			}finally{ File.Delete(fileName); }
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Searches for the first text. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileName">			. </param>
		/// <param name="pattern">			The pattern. </param>
		/// <param name="linePattern">	The line pattern. </param>
		/// <param name="height">				The height. </param>
		/// <param name="width">				The width. </param>
		/// <param name="vStep">				The v step. </param>
		/// <param name="hStep">				Amount to increment by. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	The found text. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static Matrix.TextBoxList FindText(string fileName,string pattern,string linePattern,int height,int width,int vStep,int hStep,params int[] pageNumbers){
			return FindText(fileName,pattern,linePattern,height,width,vStep,hStep,int.MaxValue,int.MinValue,0,pageNumbers);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Searches for the first text. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="fileName">			. </param>
		/// <param name="pattern">			The pattern. </param>
		/// <param name="linePattern">	The line pattern. </param>
		/// <param name="height">				The height. </param>
		/// <param name="width">				The width. </param>
		/// <param name="vStep">				The v step. </param>
		/// <param name="hStep">				Amount to increment by. </param>
		/// <param name="topMax">				The top maximum. </param>
		/// <param name="topMin">				The top minimum. </param>
		/// <param name="left">					The left. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	The found text. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static Matrix.TextBoxList FindText(string fileName,string pattern,string linePattern,int height,int width,int vStep,int hStep,int topMax,int topMin,int left,params int[] pageNumbers){
			try{A.CAcroPDDoc pdDoc = CreatePDDocInstance(fileName);
					try{return FindText(pdDoc,pattern,linePattern,height,width,vStep,hStep,topMax,topMin,left,pageNumbers);
					}finally{pdDoc.Close();Marshal.ReleaseComObject(pdDoc);}
			}catch(Exception exc){throw new Exception("PDF File Name:"+fileName,exc);}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Searches for the first text. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="pdDoc">				The pd document. </param>
		/// <param name="pattern">			The pattern. </param>
		/// <param name="linePattern">	The line pattern. </param>
		/// <param name="height">				The height. </param>
		/// <param name="width">				The width. </param>
		/// <param name="vStep">				The v step. </param>
		/// <param name="hStep">				Amount to increment by. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	The found text. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static Matrix.TextBoxList FindText(A.CAcroPDDoc pdDoc,string pattern,string linePattern,int height,int width,int vStep,int hStep,params int[] pageNumbers){
			return FindText(pdDoc,pattern,linePattern,height,width,vStep,hStep,int.MaxValue,int.MinValue,0,pageNumbers);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Searches for the first text. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="pdDoc">				The pd document. </param>
		/// <param name="pattern">			The pattern. </param>
		/// <param name="linePattern">	The line pattern. </param>
		/// <param name="height">				The height. </param>
		/// <param name="width">				The width. </param>
		/// <param name="vStep">				The v step. </param>
		/// <param name="hStep">				Amount to increment by. </param>
		/// <param name="topMax">				The top maximum. </param>
		/// <param name="topMin">				The top minimum. </param>
		/// <param name="left">					The left. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	The found text. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static Matrix.TextBoxList FindText(A.CAcroPDDoc pdDoc,string pattern,string linePattern,int height,int width,int vStep,int hStep,int topMax,int topMin,int left,params int[] pageNumbers){
			Matrix.TextBoxList tbList = new Dimok.Documents.Matrix.TextBoxList();
			foreach( int pageNumber in FileManager.MakePageNumbers(pdDoc.GetNumPages(),pageNumbers) )
				if( pageNumber <= pdDoc.GetNumPages() )
					tbList.Add(FindText(pdDoc,pattern,linePattern,height,width,vStep,hStep,topMax,topMin,left,pageNumber));
			return tbList;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Searches for the first text. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="pdDoc">				The pd document. </param>
		/// <param name="pattern">			The pattern. </param>
		/// <param name="linePattern">	The line pattern. </param>
		/// <param name="height">				The height. </param>
		/// <param name="width">				The width. </param>
		/// <param name="vStep">				The v step. </param>
		/// <param name="hStep">				Amount to increment by. </param>
		/// <param name="topMax">				The top maximum. </param>
		/// <param name="topMin">				The top minimum. </param>
		/// <param name="left">					The left. </param>
		/// <param name="pageNumber">		The page number. </param>
		///
		/// <returns>	The found text. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static Matrix.TextBox FindText(A.CAcroPDDoc pdDoc,string pattern,string linePattern,int height,int width,int vStep,int hStep,int topMax,int topMin,int left,int pageNumber){
			A.CAcroPDPage page = (A.CAcroPDPage)pdDoc.AcquirePage(pageNumber-1);
			A.CAcroPoint rect = (A.CAcroPoint)page.GetSize();
			int right = rect.x;
			if( topMax < 0 )topMax = rect.y+topMax;
			if( topMin < 0 )topMin = rect.y+topMin;
			for( int top = Math.Min(rect.y,topMax); left < right && top > Math.Max(topMin,0); top -= vStep*2-1 ){
				
				string find = GetText(pdDoc,top-vStep,left,top,right,pageNumber)[0];
				Debug.WriteLine(find);
				Debug.Flush();
				if( !Regex.IsMatch(find,linePattern,RegexOptions.IgnoreCase) )continue;

				int textEdge = GetTextEdge(height,linePattern,pdDoc,top-vStep,left,top,right,pageNumber);
				top = (height >= 0 ? textEdge : textEdge + 1) +(height >= 0 ? -vStep : vStep)/2;
				int bottom = top-1;
				
				for( ; left < right; left += hStep ){// We are on the line
					int rightNow = left+width;
					find = GetText(pdDoc,bottom,left,top,rightNow,pageNumber)[0];
					bool found = Regex.IsMatch(find,pattern,RegexOptions.IgnoreCase);
					if( !found ){
						find = GetText(pdDoc,bottom,left,top,rightNow=right,pageNumber)[0];
						found = Regex.IsMatch(find,pattern,RegexOptions.IgnoreCase);
					}
					if( found ){
						if( left > 0)
							if(hStep > 1 ){
								left -= hStep;
								hStep /= 2;
								continue;
							}
						textEdge = GetTextEdge(height,pattern,pdDoc,bottom,left,top,rightNow,pageNumber);
						top = (height >= 0 ? textEdge : textEdge + 1) +(height >= 0 ? -vStep : vStep)/2;
						bottom = top-1;

						left = GetTextLeft(5,"^"+Regex.Match(find,"\\w+").Value,pdDoc,bottom,left,top,right,pageNumber);

						find = GetText(pdDoc,
													 height >= 0 ? -1 : textEdge+height,
													 left,
													 height < 0 ? -1 : textEdge+height,
													 left+width,
													 pageNumber)[0];
						return new Matrix.TextBox(find,pageNumber,rect.y,textEdge,left);
					}
				}
			}
			return new Matrix.TextBox("",pageNumber,rect.y,-1,-1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a text left. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="step">				Amount to increment by. </param>
		/// <param name="pattern">		The pattern. </param>
		/// <param name="pdDoc">			The pd document. </param>
		/// <param name="bottom">			The bottom. </param>
		/// <param name="left">				The left. </param>
		/// <param name="top">				The top. </param>
		/// <param name="right">			The right. </param>
		/// <param name="pageNumber">	The page number. </param>
		///
		/// <returns>	The text left. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static int GetTextLeft(int step,string pattern,A.CAcroPDDoc pdDoc,int bottom,int left,int top, int right,int pageNumber){
			string leftFind;
			do{
				leftFind = GetText(pdDoc,bottom,left,top,left+=step,pageNumber)[0];
			}while( !Regex.IsMatch(leftFind,pattern,RegexOptions.IgnoreCase) && left < right );
			return step == 1 ? left : GetTextLeft(1,pattern,pdDoc,bottom,left-step,top,right,pageNumber);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a text edge. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="height">			The height. </param>
		/// <param name="pattern">		The pattern. </param>
		/// <param name="pdDoc">			The pd document. </param>
		/// <param name="bottom">			The bottom. </param>
		/// <param name="left">				The left. </param>
		/// <param name="top">				The top. </param>
		/// <param name="right">			The right. </param>
		/// <param name="pageNumber">	The page number. </param>
		///
		/// <returns>	The text edge. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static int GetTextEdge(int height,string pattern,A.CAcroPDDoc pdDoc,int bottom,int left,int top,int right,int pageNumber){
			return height >= 0 ?GetTextTop   (pattern,pdDoc,bottom,left,top,right,pageNumber) :
												  GetTextBottom(pattern,pdDoc,bottom,left,top,right,pageNumber);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a text top. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="pattern">		The pattern. </param>
		/// <param name="pdDoc">			The pd document. </param>
		/// <param name="bottom">			The bottom. </param>
		/// <param name="left">				The left. </param>
		/// <param name="top">				The top. </param>
		/// <param name="right">			The right. </param>
		/// <param name="pageNumber">	The page number. </param>
		///
		/// <returns>	The text top. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static int GetTextTop(string pattern,A.CAcroPDDoc pdDoc,int bottom,int left,int top,int right,int pageNumber){
			string find = GetText(pdDoc,top-1,left,top,right,pageNumber)[0];
			int step = Regex.IsMatch(find,pattern,RegexOptions.IgnoreCase) ? 1 : -1;
			Match m = null;
			do{
				top=top+step;
				if( top == 0 )throw new Exception("Unable to find top margin for "+pattern);
				find = GetText(pdDoc,top-1,left,top,right,pageNumber)[0];
				m = Regex.Match(find,pattern,RegexOptions.IgnoreCase);
			}while( step == 1 && m.Success || step == -1 && !m.Success );
			return top - Math.Max(step,0);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a text bottom. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="pattern">		The pattern. </param>
		/// <param name="pdDoc">			The pd document. </param>
		/// <param name="bottom">			The bottom. </param>
		/// <param name="left">				The left. </param>
		/// <param name="top">				The top. </param>
		/// <param name="right">			The right. </param>
		/// <param name="pageNumber">	The page number. </param>
		///
		/// <returns>	The text bottom. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static int GetTextBottom(string pattern,A.CAcroPDDoc pdDoc,int bottom,int left,int top,int right,int pageNumber){
			string find = GetText(pdDoc,bottom,left,bottom+1,right,pageNumber)[0];
			int step = Regex.IsMatch(find,pattern,RegexOptions.IgnoreCase) ? -1 : 1;
			Match m = null;
			do{
				bottom=bottom+step;
				if( bottom == 0 )throw new Exception("Unable to find bottom margin for "+pattern);
				find = GetText(pdDoc,bottom,left,bottom+1,right,pageNumber)[0];
				m = Regex.Match(find,pattern,RegexOptions.IgnoreCase);
			}while( step == -1 && m.Success || step == 1 && !m.Success );
			return bottom + Math.Max(step,0);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a text bottom. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="text">				The text. </param>
		/// <param name="pdDoc">			The pd document. </param>
		/// <param name="bottom">			The bottom. </param>
		/// <param name="left">				The left. </param>
		/// <param name="top">				The top. </param>
		/// <param name="right">			The right. </param>
		/// <param name="pageNumber">	The page number. </param>
		///
		/// <returns>	The text bottom. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static int GetTextBottom_(string text,A.CAcroPDDoc pdDoc,int bottom,int left,int top,int right,int pageNumber){
			string find = GetText(pdDoc,bottom,left,bottom+1,right,pageNumber)[0];
			if( Regex.IsMatch(find,text,RegexOptions.IgnoreCase) ){// bottom is inside
				do{
					find = GetText(pdDoc,--bottom,left,bottom+1,right,pageNumber)[0];
				}while( Regex.IsMatch(find,text,RegexOptions.IgnoreCase) );
				return ++bottom;
			}
			return GetTextBottom(text,pdDoc,top-1,left,top,right,pageNumber);
		}
		#endregion FindText

		#region FindForm

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Searches for the first form. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="pdfFile">		. </param>
		/// <param name="keysTable">	The keys table. </param>
		///
		/// <returns>	The found form. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static MatrixDS.tpdf_FindTextRow FindForm(byte[] pdfFile,MatrixDS.tpdf_FindTextDataTable keysTable){
			string fileName = FileManager.GetFileFromBytes(pdfFile);
			try{return FindForm(fileName,keysTable);
			}finally{File.Delete(fileName);}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Searches for the first form. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="pdfFile">		. </param>
		/// <param name="keysTable">	The keys table. </param>
		///
		/// <returns>	The found form. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static MatrixDS.tpdf_FindTextRow FindForm(string pdfFile,MatrixDS.tpdf_FindTextDataTable keysTable){
			try{A.CAcroPDDoc pdDoc = CreatePDDocInstance(pdfFile);
				try{
					foreach( MatrixDS.tpdf_FindTextRow row in keysTable )
						if( !FindText(pdDoc,row.Text,row.LineText,row.Height,row.Width,row.VStep,row.HStep,row.TopMax,row.TopMin,row.Left,1).IsEmpty )return row;
					return null;
				}finally{pdDoc.Close();Marshal.ReleaseComObject(pdDoc);}
			}catch(Exception exc){throw new Exception("PDF File Name:"+pdfFile,exc);}
		}
		#endregion

		#region Decript

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Decrypts. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="inFile">				The in file. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] Decrypt(byte[] inFile,params int[] pageNumbers){
			return FileManager.GetBytesFromFile(Decrypt(FileManager.GetFileFromBytes(inFile),pageNumbers),true);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Decrypts. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="inFile">				The in file. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string Decrypt(string inFile,params int[] pageNumbers){
			string fileTemp = Decrypt(inFile,"",pageNumbers);
			File.Delete(inFile);
			File.Move(fileTemp,inFile);
			return inFile;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Decrypts. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="inFile">				The in file. </param>
		/// <param name="outFile">			The out file. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string Decrypt(string inFile,string outFile,params int[] pageNumbers){
			pageNumbers = FileManager.MakePageNumbers(PageCount_Prep(inFile),pageNumbers);
			IDocClass iDoc = new IDocClass();
			if(!iDoc.OpenMem(FileManager.GetBytesFromFile(inFile),"")) throw new Exception("Couldn't load pdf template for PrepTool input");
			outFile = FileManager.BuildFullFileName(outFile,true);
			PDocClass pDoc = new PDocClass();
			try{
				if(!pDoc.New(outFile,592,842)) throw new Exception("Couldn't create a new PDF file for output");
				if(!pDoc.InputOpen(inFile)) throw new Exception("Couldn't open PDF file for output");
				foreach( int pageNumber in pageNumbers )
					if(!pDoc.InputCopyPages(pageNumber,pageNumber)) throw new Exception("Couldn't copy PDF page(s) into PDF output");
				if(!pDoc.Close()) throw new Exception("Couldn't close PDF output");
				bool m = iDoc.Close();
				return outFile;
			}catch{
				pDoc.Close();
				if( File.Exists(outFile) )File.Delete(outFile);
				throw;
			}
		}
		#endregion

		#region Slice

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Uses Acrobat. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="pdf">					The pdf. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[][] Slice(byte[] pdf,params int[] pageNumbers){
			Dyno.Merger.PdfDocument doc = new ceTe.DynamicPDF.Merger.PdfDocument(pdf);
			ArrayListEx alNumbers =  FileManager.MakePageNumbers(doc.Pages.Count,pageNumbers);
			ArrayListEx alPages = new ArrayListEx();
			foreach( int i in alNumbers )
				try{
					Dyno.Merger.MergeDocument pdfDoc = new Dyno.Merger.MergeDocument(doc,i,1,new Dyno.Merger.MergeOptions(true));
					pdfDoc.InitialPageZoom = Dyno.PageZoom.FitWidth;
					alPages.Add(pdfDoc.Draw());
				}catch(Exception exc){ throw new Exception("Page:"+i+" out of ["+alNumbers+"]",exc); }
			return alPages;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Uses Acrobat. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="pdf">	The pdf. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static byte[][] Slice(byte[] pdf){
			string inFile = FileManager.GetFileFromBytes(pdf,Path.GetTempFileName(),false);
			IDocClass iDoc = new IDocClass();
			if(!iDoc.OpenMem(pdf,"")) throw new Exception("Couldn't load pdf template for PrepTool input");
			byte[][] output = new byte[iDoc.NumPages()][];
			for(int i=0;i<iDoc.NumPages();i++) {
				string temp = Path.GetTempFileName();
				PDocClass pDoc = new PDocClass();
				if(!pDoc.New(temp,592,842)) throw new Exception("Couldn't create a new PDF file for output");
				if(!pDoc.InputOpen(inFile)) throw new Exception("Couldn't open PDF file for output");
				if(!pDoc.InputCopyPages(i+1,i+1)) throw new Exception("Couldn't copy PDF page(s) into PDF output");
				if(!pDoc.Close()) throw new Exception("Couldn't close PDF output");
				output[i] = FileManager.GetBytesFromFile(temp,true);
			}
			bool m = iDoc.Close();
			File.Delete(inFile);
			return output;
		}
		#endregion
		
		#region Helpers ==================

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Creates the rectangle instance. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static Acrobat.CAcroRect CreateRectInstance() {
			return (Acrobat.CAcroRect)Activator.CreateInstance(Type.GetTypeFromProgID("AcroExch.Rect",true),true);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Creates a form application instance. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static AFORMAUTLib.AFormApp CreateAFormAppInstance() {
			Type oAForm = Type.GetTypeFromProgID("AFormAut.App",true);
			return (AFORMAUTLib.AFormApp)Activator.CreateInstance(oAForm,true);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Creates a pd document instance. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileName">	. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static Acrobat.CAcroPDDoc CreatePDDocInstance(string fileName){
			Acrobat.CAcroPDDoc pdDoc = (Acrobat.CAcroPDDoc)Activator.CreateInstance(Type.GetTypeFromProgID("AcroExch.PDDoc",true),true);
			FileManager.WaitToLoad(fileName,15*1000);
			pdDoc.Open(fileName);
			return pdDoc;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Creates a v document instance. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static Acrobat.CAcroAVDoc CreateAVDocInstance(){ return CreateAVDocInstance(""); }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Creates a v document instance. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="FileLoadException">	Thrown when fileload. </exception>
		/// <exception cref="Exception">					Thrown when exception. </exception>
		///
		/// <param name="fileName">	. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static Acrobat.CAcroAVDoc CreateAVDocInstance(string fileName){
			Acrobat.CAcroAVDoc avDoc = (Acrobat.CAcroAVDoc)Activator.CreateInstance(Type.GetTypeFromProgID("AcroExch.AVDoc",true),true);
			try{
				if( fileName != "" ){
					FileManager.WaitToLoad(fileName,15*1000);
					StreamReader sr = File.OpenText(fileName);
					try {
						if( sr.BaseStream.Length == 0 )
							throw new System.IO.FileLoadException("Acrobat can't load empty file ["+fileName+"].");
					}
					finally {
						sr.Close();
					}
					Thread.Sleep(300);
					avDoc.Open(fileName,"");
					if( Convert.ToInt32(avDoc.IsValid()) != -1 )
						throw new System.IO.FileLoadException("Acrobat can't load file "+fileName);
				}
			}catch(Exception exc){
				try{ avDoc.Close(1); }catch{}
				throw exc;
			}
			return avDoc;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Dispose of this object, cleaning up any resources it uses. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="refs">	A variable-length parameters list containing references. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void Dispose(params object[] refs){
			foreach( object o in refs )
				while( o != null && Marshal.ReleaseComObject(o) > 0 ){}; 
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Calculates the end page. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="pageStart">	[in,out] . </param>
		/// <param name="count">			-1 - all pages. </param>
		///
		/// <returns>	The calculated end page. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static int CalcEndPage(ref int pageStart,int count){
			pageStart = Math.Max(pageStart,1);
			return count <= 0 ? - 1 : pageStart + count - 1;
		}
		#endregion 
	
		#region IDisposable Members

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Dispose of this object, cleaning up any resources it uses. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public void Dispose() {
			if( Doc != null ){
				Doc.Close();
				Marshal.ReleaseComObject(Doc);
				Doc = null;
			}
			if( IsTemp && File.Exists(FileName) )File.Delete(FileName);
		}
		#endregion
	}
}